home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1997 September
/
Macworld (1997-09).dmg
/
Serious Software
/
Cherwell Scientific Demos
/
pro Fit
/
pro Fit 5.0 demo (fpu).sea
/
pro Fit 5.0 demo (fpu)
/
External Modules
/
External modules sources
/
C
/
Contour plotting
/
ContourData.c
< prev
next >
Wrap
Text File
|
1996-06-08
|
15KB
|
513 lines
#include "proFit_interface.h"
#ifndef __MODULE_UTILITIES__
#include "ModuleUtilities.h"
#endif
#ifndef __STRING_SUPPORT__
#include "StringSupport.h"
#endif
#ifndef __CONTOUR_PLOTTER__
#include "ContourPlotter.h"
#endif
/* the following struct contains the variables that we use in Run() */
/* We collect them into a struct such that we can pass them all simply */
/* by passing a pointer to this struct */
typedef struct
{
double firstLevel; /* default values */
double lastLevel;
double levelStep;
long x1Min, x1Max; // range for x1
long x2Min, x2Max; // range for x2
Boolean useCurrentGraph; // true if we should draw into current graph
long customContourWindow; // 0 or ref to a custom contour level window
long customContourColumn; // 0 or id of a custom contour column
}MyStaticVars;
/***************************************************************************************/
void SetUp ( short* const moduleKind, /* return isFunction or isProgram */
Str255 name, /* the name of the program of function */
/* (pascal string) */
long* const requiredGlobals, /* the number of bytes to be allocated */
/* in ExtModulesParamBlock.globals. */
/* Set to 0 if you don't use this feature */
ExtModulesParamBlock* pb) /* can be ignored in most cases */
/* called when your code resource is linked to proFit */
{
*moduleKind=isProgram; /* we define a program */
SetPascalStr(name,"\pContour Plot Data...",255); /* its name */
*requiredGlobals = sizeof(MyStaticVars); /* our static vars */
}
/***************************************************************************************/
void InitializeProg (ExtModulesParamBlock* pb)
/* Can be left emtpy if not needed. */
/* Only used by advanced programmers. */
/* called when the resource is linked to proFit after SetUp was called */
{
MyStaticVars* vs = (MyStaticVars*)pb->globals;
vs->firstLevel = -1; // set default values
vs->lastLevel = 1;
vs->levelStep = 0.2;
vs->x1Min = 1;
vs->x1Max = 5;
vs->x2Min = 1;
vs->x2Max = 5;
vs->useCurrentGraph = true;
vs->customContourWindow = 0;
vs->customContourColumn = 0;
}
/***************************************************************************************/
enum {
firstLevelTitleItem = 3,
lastLevelTitleItem,
distanceTitleItem,
firstLevelItem = 6,
lastLevelItem,
distanceItem,
dataWindowItem = 23,
x1FirstItem = 10,
x1LastItem = 11,
x2FirstItem = 14,
x2LastItem = 16,
useCurrentGraphItem = 17,
regularContourItem = 18,
customContourItem,
windowItem = 20,
columnItem,
helpButtonItem = 22
};
static Boolean GetRow(DialogData* dlg, short itemID, long* const value)
{
long val;
long nrRows = NrRows();
if (MyGetLongItem(dlg, itemID, &val) == false) return false;
if (val < 1)
{ MySelectItemText(dlg, itemID, 0, 0x7FFF);
SysBeep(30);
return false;
}
if (val > nrRows) val = nrRows;
*value = val;
return true;
}
static Boolean GetColumn(DialogData* dlg, short itemID, long* const value)
{
long val;
long nrCols = NrCols();
if (MyGetLongItem(dlg, itemID, &val) == false) return false;
if (val < 1)
{ MySelectItemText(dlg, itemID, 0, 0x7FFF);
SysBeep(30);
return false;
}
if (val > nrCols) val = nrCols;
*value = val;
return true;
}
static Boolean MyFunction(double x1, double x2, double* const x3, void* param)
{
long row = RoundDouble(x2);
long col = RoundDouble(x1);
if (TestData(row, col) == false) return false;
*x3 = GetData(row, col);
return true;
}//MyFunction
static void ShowHideItems(DialogData* const dlg)
// shows and hides the items in the lower part of the dialog
{
static const char regularItems[] = {firstLevelTitleItem, lastLevelTitleItem,
distanceTitleItem, firstLevelItem, lastLevelItem, distanceItem, 0};
static const char customItems[] = {windowItem, columnItem, 0};
char* itemsToShow;
char* itemsToHide;
if (MyGetItemValue(dlg, regularContourItem))
{ itemsToShow = (char*)regularItems;
itemsToHide = (char*)customItems;
}
else
{ itemsToShow = (char*)customItems;
itemsToHide = (char*)regularItems;
}
while (*itemsToShow) MyShowItem(dlg, *itemsToShow++);
while (*itemsToHide) MyHideItem(dlg, *itemsToHide++);
}
void Run(ExtModulesParamBlock* pb)
/* called to execute the program */
{
PlottingData* v=nil;
MyStaticVars* vs = (MyStaticVars*)pb->globals;
Boolean useCurrentGraph = true;
Handle myMemory = nil;
long oldDataWindow = GetCurrentWindow(dataType);
if (TestStop()) return;
{ DialogData* dlg;
short itemHit;
short resFile = FSpOpenResFile(GetModuleFile(), fsCurPerm);
long x1Min = vs->x1Min, x1Max = vs->x1Max;
long x2Min = vs->x2Min, x2Max = vs->x2Max;
long customContourWindow = vs->customContourWindow;
long customContourColumn = vs->customContourWindow;
Boolean customContours;
long dataWindow = oldDataWindow;
if (resFile == -1) return;
if (oldDataWindow==0) // if no data window
{
SysBeep(30);
MyAlert(30002); // there's no data window, dammit
CloseResFile(resFile);
return;
}
dlg = MyGetNewDialog(30000, 1, 2);
if (dlg == nil) StopExecution();
else
{
if (FrontmostWindow(drawingType) == 0 || GetCurrentGraph() == 0) // if no drawing window or now current graph
{ useCurrentGraph = false;
MyHiliteItem(dlg, useCurrentGraphItem, 255); // disable
}
if (vs->customContourWindow != 0 && GetWindowType(vs->customContourWindow)==0) // if window does not exist anymore
{ vs->customContourWindow = 0;
vs->customContourColumn = 0;
}
else if (vs->customContourWindow)
{
SetCurrentWindow(vs->customContourWindow);
if (vs->customContourColumn > NrCols() || GetColType(vs->customContourColumn) == textColumn) // if window has become smaller
vs->customContourColumn = 1;
SetCurrentWindow(oldDataWindow);
}
customContours = vs->customContourWindow != 0;
MySetExtendedItem(dlg, firstLevelItem, vs->firstLevel);
MySetExtendedItem(dlg, lastLevelItem, vs->lastLevel);
MySetExtendedItem(dlg, distanceItem, vs->levelStep);
MakeWindowPopup(dlg, dataWindowItem, dataType);
SetItemGeneral(dlg, dataWindowItem, &dataWindow);
MySetLongItem(dlg, x1FirstItem, x1Min);
MySetLongItem(dlg, x1LastItem, x1Max);
MySetLongItem(dlg, x2FirstItem, x2Min);
MySetLongItem(dlg, x2LastItem, x2Max);
MySetItemValue(dlg, useCurrentGraphItem, useCurrentGraph);
MakeWindowPopup(dlg, windowItem, dataType);
if (vs->customContourWindow)
SetItemGeneral(dlg, windowItem, &vs->customContourWindow);
MakeColumnPopup(dlg, columnItem, windowItem, 1);
if (vs->customContourColumn)
MySetItemValue(dlg, columnItem, vs->customContourColumn);
MySetItemValue(dlg, regularContourItem, !customContours);
MySetItemValue(dlg, customContourItem, customContours);
if (FrontmostWindow(dataType)==0) // if no data window
MyHiliteItem(dlg, customContourItem, 255); // disable custom
ShowHideItems(dlg);
MySelectItemText(dlg, x1FirstItem, 0, 0x7FFF);
MyShowDialog(dlg);
do
{
MyModalDialog(dlg, &itemHit);
switch(itemHit)
{
case regularContourItem:
MySetItemValue(dlg, customContourItem, 0);
ShowHideItems(dlg);
break;
case customContourItem:
MySetItemValue(dlg, regularContourItem, 0);
ShowHideItems(dlg);
break;
case helpButtonItem:
MyAlert(30003); // bring up help alert
break;
case ok:
{
double firstLevel;
double lastLevel;
double levelStep;
GetItemGeneral(dlg, dataWindowItem, &dataWindow);
SetCurrentWindow(dataWindow);
if (!( MyGetExtendedItem(dlg, firstLevelItem, &firstLevel) &&
MyGetExtendedItem(dlg, lastLevelItem, &lastLevel) &&
MyGetExtendedItem(dlg, distanceItem, &levelStep) &&
GetColumn(dlg, x1FirstItem, &x1Min) &&
GetColumn(dlg, x1LastItem, &x1Max) &&
GetRow(dlg, x2FirstItem, &x2Min) &&
GetRow(dlg, x2LastItem, &x2Max)))
itemHit = 0; // if bad entry
else if (firstLevel > lastLevel)
{ MySelectItemText(dlg, firstLevelItem, 0, 0x7FFF);
SysBeep(30);
itemHit = 0;
}
else if (levelStep <= 1e-100 || (lastLevel-firstLevel)/levelStep > 1000)
{ MySelectItemText(dlg, distanceItem, 0, 0x7FFF);
SysBeep(30);
itemHit = 0;
}
else if (x1Min >= x1Max)
{ MySelectItemText(dlg, x1FirstItem, 0, 0x7FFF);
SysBeep(30);
itemHit = 0;
}
else if (x2Min >= x2Max)
{ MySelectItemText(dlg, x2FirstItem, 0, 0x7FFF);
SysBeep(30);
itemHit = 0;
}
else
{
if (MyGetItemValue(dlg, regularContourItem)) // if regular contour levels
{ vs->firstLevel = firstLevel;
vs->lastLevel = lastLevel;
vs->levelStep = levelStep;
vs->customContourWindow = 0;
vs->customContourColumn = 0;
} else
{ GetItemGeneral(dlg, windowItem, &vs->customContourWindow); // get window
vs->customContourColumn = MyGetItemValue(dlg, columnItem); // and column
}
vs->x1Min = x1Min;
vs->x1Max = x1Max;
vs->x2Min = x2Min;
vs->x2Max = x2Max;
useCurrentGraph = MyGetItemValue(dlg, useCurrentGraphItem);
}
}// case ok
}//switch
}while (itemHit != ok && itemHit != cancel);
if (itemHit == cancel) StopExecution();
MyDisposeDialog(dlg);
}
CloseResFile(resFile);
}
if (TestStop()) return;
SetWaitTitle("\pCalculating matrix");
{
long nrRows = vs->x2Max - vs->x2Min + 1;
long nrCols = vs->x1Max - vs->x1Min + 1;
v = InitContourPlotter(nrRows, nrCols, vs->x1Min, vs->x1Max,
vs->x2Min, vs->x2Max);
if (v==nil)
{ StopExecution();
goto done;
}
if (!CalculateContourMatrix(MyFunction, vs, v))
{ StopExecution();
goto done;
}
}
SetLineStyle(1,1);
SetLineColor(0,0,0);
if (useCurrentGraph == false)
{ CreateNewGraph(vs->x1Min, vs->x1Max, vs->x2Min, vs->x2Max, 0, 0);
if (TestStop()) goto done;
}
DisableDrawingUpdates(); // avoids flicker in drawing window
{
Boolean allLevelsDone=false;
double level;
long row = 1;
Boolean regularLevels = vs->customContourWindow==0; // true if regular levels, false if custom levels
long levelCol = vs->customContourColumn; // the column for custom levels
long thickCol=0, dashCol=0, rCol=0, gCol=0, bCol=0; // the columns for thickness, dash, rgb-values
long nameCol=0;
if (regularLevels)
level = vs->firstLevel;
else // parse for special additional columns
{
Boolean columnsDone = false;
long i = levelCol+1;
SetCurrentWindow(vs->customContourWindow);
while (i<=NrCols() && !columnsDone)
{
Str255 s;
GetColName(s, i);
if (GetColType(i) != textColumn)
{
if (EqualStr255(s, "\pthickness"))
thickCol = i;
else if (EqualStr255(s, "\pdash"))
dashCol = i;
else if (EqualStr255(s, "\pr"))
rCol = i;
else if (EqualStr255(s, "\pg"))
gCol = i;
else if (EqualStr255(s, "\pb"))
bCol = i;
else columnsDone = true;
}
else if (EqualStr255(s, "\pname"))
nameCol = i;
else columnsDone = true;
i += 1;
}
if (rCol == 0 || gCol == 0 || bCol == 0) // they must all be != 0
rCol = gCol = bCol = 0;
if (oldDataWindow) SetCurrentWindow(oldDataWindow);
}
while (!allLevelsDone)
{
Str255 curveName;
Str255 status;
double thick = 1.0;
double dash = 1;
double r=0, g=0, b=0;
if (!regularLevels)
{
SetCurrentWindow(vs->customContourWindow);
while (!TestData(row, levelCol))
{ if (row >= NrRows())
{ allLevelsDone = true;
break; // if all done
}
row += 1;
}
if (allLevelsDone) break;
level = GetData(row, levelCol);
if (thickCol != 0 && TestData(row, thickCol))
thick = GetData(row, thickCol);
if (dashCol != 0 && TestData(row, dashCol))
dash = GetData(row, dashCol);
if (rCol != 0 && TestData(row, rCol) && TestData(row, gCol) && TestData(row, bCol))
{ r = GetData(row, rCol);
g = GetData(row, gCol);
b = GetData(row, bCol);
}
if (nameCol != 0)
GetCell(curveName, row, nameCol);
row += 1;
if (row > NrRows()) allLevelsDone = true;
if (oldDataWindow) SetCurrentWindow(oldDataWindow);
}
if (nameCol == 0)
NumberToStr255(level, curveName, 0, 3);
Concat2(status, "\plevel: ", curveName);
SetLineStyle(thick, dash);
SetLineColor(r,g,b);
SetWaitTitle(status);
OpenCurve(curveName);
if (!DrawContour(level, v)) goto done;
CloseCurve();
SetLineStyle(1,1);
SetLineColor(0,0,0);
if (regularLevels)
{ level += vs->levelStep;
allLevelsDone = level > vs->lastLevel;
}
}
}
done: // clean up
DisposeContourPlotter(v); // does nothing if v==nil
if (oldDataWindow) SetCurrentWindow(oldDataWindow);
if (myMemory != nil) DisposeHandle(myMemory);
}
/***************************************************************************************/
void CleanUp (ExtModulesParamBlock* pb)
/* called when your code resource is not needed anymore */
/* in most cases, this function can be empty */
{
}
/***************************************************************************************/
/* for functions, not used here: */
/***************************************************************************************/
void InitializeFunc (
Boolean* const hasDerivatives, /* set to true if you define the function Derivatives to calculate the partial derivatives of your parameters */
Str255 descr1stLine, /* string 1 to appear in parameter window */
Str255 descr2ndLine, /* string 2 to appear in parameter window */
short* const numberOfParams, /* the number of parameters of your function */
DefaultParamInfo* const a0, /* the default names, values etc. of your parameters */
ExtModulesParamBlock* pb) /* can be ignored in most cases */
{}
void Func ( double x, /* the x-value */
ParamArray a, /* the parameters */
double* const y, /* the y-value to be returned */
ExtModulesParamBlock* pb) /* can be ignored in most cases */
{}
void Derivatives(double x, /* the x-value */
ParamArray a, /* the parameters */
ParamArray dyda, /* the derivatives to be returned */
ExtModulesParamBlock* pb)
{}
short Check(short paramNo, /* the parameter that was changed */
DefaultParamInfo* const a0, /* the default names, values etc of the paramters */
ExtModulesParamBlock* pb)
{paramNo--;/*the array a0 is indexed from zero. Decrement paramNo so that it corresponds to the inices of a0*/
return ok;
}
void First ( ParamArray a, /* the new parameters */
ExtModulesParamBlock* pb)
{}
void Last (ExtModulesParamBlock* pb)
{}